package jsurftwmm;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.border.Border;
import jopensurf.SURFInterestPoint;

import jopensurf.Surf;
import jopensurf.SurfCompare;

/**
 *
 * @author Luk�
 */
public class WindowUI extends JPanel implements ActionListener, Serializable {

    static private final String newline = "\n";
    JButton openButton, pickUpFolderButton, exitButton;
    JFrame progress = new JFrame("JProgressBar Sample");
    JProgressBar progressBar = new JProgressBar();
    JTextArea log;
    JFileChooser fc;
    JFileChooser dirChooser;
    JLabel infoLabel;
    JLabel imageHeadline;
    SurfImage image;
    JPanel imagePanel;
    SurfImage image2;
    ArrayList<SurfImage> imagesToCompare = new ArrayList<SurfImage>();

    WindowUI() {
        super(new BorderLayout());
        log = new JTextArea(5, 50);
        log.setMargin(new Insets(5, 5, 5, 5));
        log.setEditable(false);
        JScrollPane logScrollPane = new JScrollPane(log);



        fc = new JFileChooser();
        //dirChooser = new JFile

        openButton = new JButton("Open a File..."/*,
                 createImageIcon("images/Open16.gif")*/);
        openButton.addActionListener(this);

        pickUpFolderButton = new JButton("Pick up folder..."/*,
                 createImageIcon("images/Save16.gif")*/);
        pickUpFolderButton.addActionListener(this);

        exitButton = new JButton("Exit");
        exitButton.addActionListener(this);


        JPanel buttonPanel = new JPanel();
        buttonPanel.add(openButton);
        buttonPanel.add(pickUpFolderButton);
        buttonPanel.add(exitButton);

        infoLabel = new JLabel("Any pictures for compare haven't been choosen yet", JLabel.CENTER);
        imagePanel = new JPanel();
        imagePanel.setLayout(new GridLayout(0, 1));
        imagePanel.add(infoLabel);

        add(buttonPanel, BorderLayout.PAGE_START);
        add(logScrollPane, BorderLayout.CENTER);
        add(imagePanel, BorderLayout.PAGE_END);
    }
    File f2;
    private SurfImage threadResult;

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == openButton) {
            int returnVal = fc.showOpenDialog(WindowUI.this);

            if (returnVal == JFileChooser.APPROVE_OPTION) {
                File file = fc.getSelectedFile();
                //This is where a real application would open the file.

                /*BufferedImage image = null;
                 try {
                 image = ImageIO.read(file);
                 } catch (IOException ex) {
                 Logger.getLogger(WindowUI.class.getName()).log(Level.SEVERE, null, ex);
                 }
                 BufferedImage im = null;
                 try {
                 im = getScaledImage(image, 100, 100);
                 } catch (IOException ex) {
                 Logger.getLogger(WindowUI.class.getName()).log(Level.SEVERE, null, ex);
                 }

                 // catch IOException
                 previewImage.setIcon(new ImageIcon(im));
                 previewImage.setText("");

                 JFrame frame = (JFrame) this.getParent();
                 frame.pack();*/

                try {
                    log.append("Opening: " + file.getName() + "." + newline);
                    image = new SurfImage(ImageIO.read(file), file.getName());

                    log.append("Initalizing SURF library." + newline);
                    Surf mySurf = new Surf(image.getImage());

                    //List<InterestPoint> matchingPoint = (List<InterestPoint>) mySurf.getMatchingPoints(mySurf, false);
                    log.append("Counting Matching point...." + newline);
                    image.setMatchingPoint(mySurf.getMatchingPoints(mySurf, false, 0.65d));
                    log.append("Counting done." + newline);

                    log.append("Counting free oriented interest points...." + newline);
                    image.setFreeOrientedInterestPoints(mySurf.getFreeOrientedInterestPoints());
                    log.append("Counting done." + newline);

                } catch (IOException e1) {
                    log.append("Opening: " + file.getName() + "Failed." + newline);
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }


            } else {
                log.append("Open command cancelled by user." + newline);
            }
            log.setCaretPosition(log.getDocument().getLength());


        } else if (e.getSource() == pickUpFolderButton) {
            //TODO: dodelat

            fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
            fc.setMultiSelectionEnabled(true);

            fc.setCurrentDirectory(new java.io.File("C://test/car"));
            // chooser.setDialogTitle(choosertitle);
            // fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
            //
            // disable the "All files" option.
            //
            //fc.setAcceptAllFileFilterUsed(false);

            int returnVal = fc.showOpenDialog(WindowUI.this);

            if (returnVal == JFileChooser.APPROVE_OPTION) {


                File files[] = fc.getSelectedFiles();
                //fc.getCurrentDirectory().l


                for (File f : files) {
                    System.out.println(f.getName());
                }

                log.append("Processing files from dir...." + newline);
                ThreadWithResult[] thread = new ThreadWithResult[files.length];


                List<String> textFiles = textFiles(files[0].getParent());

                int help = 7;
                if (thread.length > help) {
                    for (int i = 0; i < help; i++) {
                        File f = files[i];
                        thread[i] = new ThreadWithResult(f, textFiles.contains(f.getName() + ".dat"));
                        thread[i].start();
                    }
                    for (int i = help; i < thread.length; i++) {
                        while (thread[i - help].isAlive()) {
                        }
                        File f = files[i];
                        thread[i] = new ThreadWithResult(f, textFiles.contains(f.getName() + ".dat"));
                        thread[i].start();
                    }
                } else {
                    for (int i = 0; i < files.length; i++) {
                        File f = files[i];
                        thread[i] = new ThreadWithResult(f, textFiles.contains(f.getName() + ".dat"));
                        thread[i].start();
                    }
                }

                //progress.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                Container content = progress.getContentPane();
                int value = 100 / files.length;
                progressBar.setValue(0);
                progressBar.setStringPainted(true);
                Border border = BorderFactory.createTitledBorder("Counting...");
                progressBar.setBorder(border);
                content.add(progressBar, BorderLayout.NORTH);
                progress.setSize(300, 100);
                progress.setVisible(true);

                for (int i = 0; i < thread.length; i++) {
                    ObjectOutputStream out = null;
                    try {
                        while (thread[i].isAlive()) {
                        }

                        progressBar.setValue(i * value);

                        this.imagesToCompare.add(thread[i].image2);
                        System.out.println("Counting done. " + thread[i].image2.getName() + " M: " + imagesToCompare.get(i).countMatchingPoint());
                        System.out.println("Done " + i + "/" + files.length);
                        log.append("Counting done. " + thread[i].image2.getName() + " M: " + imagesToCompare.get(i).countMatchingPoint() + newline);
                        log.append("Done " + i + "/" + files.length + newline);
                        //log.repaint();
                        this.updateUI();
                        if (!textFiles.contains(imagesToCompare.get(i).getName() + ".dat")) {
                            out = new ObjectOutputStream(new FileOutputStream(thread[i].f.getPath() + ".dat"));
                            out.writeObject(imagesToCompare.get(i).getName());
                            out.writeObject(imagesToCompare.get(i).getfreeOrientedInterestPoints());
                            out.writeObject(imagesToCompare.get(i).getMatchingPoint());
                            out.close();
                            textFiles.add(imagesToCompare.get(i).getName() + ".dat");
                        }
                    } catch (IOException ex) {
                        Logger.getLogger(WindowUI.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }


               log.append("All done " + imagesToCompare.size());

                /* for (File f : files) {
                 try {
                 SurfImage sImage = new SurfImage(ImageIO.read(f), f.getName());
                 Surf surf = new Surf(sImage.getImage());
                 sImage.setMatchingPoint(surf.getMatchingPoints(surf, false));
                 sImage.setFreeOrientedInterestPoints(surf.getFreeOrientedInterestPoints());
                 this.imagesToCompare.add(sImage);
                 } catch (IOException e1) {
                 // TODO Auto-generated catch block
                 e1.printStackTrace();
                 }
                 }*/
                //log.append("Done!" + newline);

                Collections.sort(imagesToCompare, new MyComparator());

                for (int i = 0; i < imagesToCompare.size(); i++) {
                    System.out.println(imagesToCompare.get(i).getName() + " M: " + imagesToCompare.get(i).countMatchingPoint());
                }

                if (imagesToCompare.size() != 0) {
                    setUpResultView();
                }
            } else {
                log.append("Open command cancelled by user." + newline);
            }




        }
    }

    public class ThreadWithResult extends Thread {

        File f;
        SurfImage image2;
        boolean fileExist;

        ThreadWithResult(File f, boolean exist) {
            this.f = f;
            this.fileExist = exist;
        }

        @Override
        public void run() {
            try {
                SurfImage sImage = null;
                if (fileExist) {
                    ObjectInputStream in = new ObjectInputStream(new FileInputStream(f.getPath() + ".dat"));
                    sImage = new SurfImage(ImageIO.read(f), (String) in.readObject());
                    sImage.setFreeOrientedInterestPoints((List<SURFInterestPoint>) in.readObject());
                    sImage.setMatchingPoint((Map<SURFInterestPoint, SURFInterestPoint>) in.readObject());
                    in.close();
                } else {
                    sImage = new SurfImage(ImageIO.read(f), f.getName());
                    Surf surf = new Surf(sImage.getImage());
                    sImage.setMatchingPoint(surf.getMatchingPoints(surf, false, 0.65d));
                    sImage.setFreeOrientedInterestPoints(surf.getFreeOrientedInterestPoints());
                }

                image2 = sImage;
                System.out.println("Image done. " + image2.getName() + " done. M: " + image2.countMatchingPoint());
                log.append("Image done. " + image2.getName() + " done. M: " + image2.countMatchingPoint() + newline);
            } catch (ClassNotFoundException ex) {
                //Logger.getLogger(WindowUI.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }

            // do something that calculates "result"  

        }
    }

    List<String> textFiles(String directory) {
        List<String> textFiles = new ArrayList<String>();
        File dir = new File(directory);
        for (File file : dir.listFiles()) {
            if (file.getName().endsWith(".dat")) {
                textFiles.add(file.getName());
            }
        }
        return textFiles;
    }

    private void setUpResultView() {
        this.infoLabel.setText("Selected pictures:");

        for (final SurfImage simg : imagesToCompare) {
            JLabel imageLabel = new JLabel("<html><u>" + simg.getName() + "</u></htmk>", JLabel.CENTER);
            imageLabel.addMouseListener(new MouseAdapter() {
                public void mousePressed(MouseEvent me) {
                    SurfCompare mySurfComp = new SurfCompare(image.getImage(), simg.getImage());
                    //mySurfComp.display();
                    JFrame f = new JFrame();
                    f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                    f.add(new JScrollPane(mySurfComp));
                    //f.setSize(mySurfComp.getImImageAWidth+mImageBWidth,Math.max(mImageAHeight,mImageBHeight));
                    f.setSize(image.getImage().getWidth() + simg.getImage().getWidth(), Math.max(image.getImage().getHeight(), simg.getImage().getHeight()));
                    f.setLocation(0, 0);
                    f.setVisible(true);
                }
            });
            this.imagePanel.add(imageLabel);
        }
        this.updateUI();
    }
    /*
     public BufferedImage getScaledImage(BufferedImage image, int width, int height) throws IOException {
     int imageWidth = image.getWidth();
     int imageHeight = image.getHeight();

     double scaleX = (double) width / imageWidth;
     double scaleY = (double) height / imageHeight;
     AffineTransform scaleTransform = AffineTransform.getScaleInstance(scaleX, scaleY);
     AffineTransformOp bilinearScaleOp = new AffineTransformOp(scaleTransform, AffineTransformOp.TYPE_BILINEAR);

     return bilinearScaleOp.filter(
     image,
     new BufferedImage(width, height, image.getType()));
     }

     protected static ImageIcon createImageIcon(String path) {
     java.net.URL imgURL = WindowUI.class.getResource(path);
     if (imgURL != null) {
     return new ImageIcon(imgURL);
     } else {
     System.err.println("Couldn't find file: " + path);
     return null;
     }
     }
     */
}
